#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string>
#include <string.h>
#include "comm.hpp"
#include "Thread.hpp"

//客户端的任务：一个线程发送消息，一个线程一直接受消息

// TCP协议中，客户端是不用绑定端口了，绑定之后只能运行一个client的程序属于自己人为设定的，
// 而从服务器那边得到的客户机连接端口号（是系统自动分配的）与这边客户机绑定的端口号根本是不相关的，所以客户端绑定也就失去了意义。

void Usage(std::string proc)
{
    cout << "Usage: " << proc << "server_ip  server_port" << endl;
}

int InitClient(std::string &serverip, uint16_t serverport, struct sockaddr_in *server)
{
    // 1. 创建socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        std::cerr << "socket error" << std::endl;
        return -1;
    }
    // 2. client要不要bind？一定要，client也要有自己的IP和PORT。要不要显式[和server一样用bind函数]的bind？不能！不建议！！

    memset(server, 0, sizeof(struct sockaddr_in));
    server->sin_family = AF_INET;
    server->sin_port = htons(serverport);
    server->sin_addr.s_addr = inet_addr(serverip.c_str());

    return sockfd;
}

void RecvMessage(const int& socketfd,std::string name)
{
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    std::string message;
    int fd = OpeanDev("/dev/pts/6",O_WRONLY);
    while (1)
    {
        char buffer[1024];
        ssize_t n = recvfrom(socketfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&peer, &len);
        if (n > 0)
        {
            buffer[n] = 0;
            write(fd,buffer,strlen(buffer));
            //std::cout << "server echo# " << buffer << std::endl;
        }
    }
}

void SendMessage(const int& socketfd,struct sockaddr_in& addr,std::string name)
{
    std::string message;
    while(1)
    {
        printf("%s |Enter:",name.c_str());
        fflush(stdout);
        std::getline(std::cin,message);
        cout<<message.size()<<endl;
        size_t n = sendto(socketfd, message.c_str(), message.size(), 0, (struct sockaddr *)&addr, sizeof(addr));
    }
}

int main(int argc, char *argv[])
{

    if (argc != 3)
    {
        Usage(argv[0]);
        exit(-1);
    }

    std::string ip = argv[1];
    uint16_t port = stoi(argv[2]);

    struct sockaddr_in addr;
    int socketfd = InitClient(ip, port, &addr);

    func_t r = std::bind(&RecvMessage,socketfd,std::placeholders::_1);
    func_t s = std::bind(&SendMessage,socketfd,addr,std::placeholders::_1);

    Thread Recver(r,"Recver");
    Thread Sender(s,"sender");

    Recver.Strat();
    Sender.Strat();

    Recver.join();
    Sender.join();

    return 0;
}